<script setup>
import { computed, nextTick, ref, watch } from 'vue';

import { useAccessStore } from '@vben/stores';

// import videojs from "video.js"
// import "video.js/dist/video-js.css"
import { imgUrl } from '#/UrlsConfig.js';

const props = defineProps({
  uploadUrl: {
    type: String,
    default: '/energy-admin/common/uploadFile',
  },
  uploadData: {
    type: Object,
    default: () => ({ module: ' ' }),
  },
  // 上传限制
  uploadLimit: {
    type: Number,
    default: 10,
  },
  // 上传列表
  fileList: {
    type: Array,
    default: () => [],
  },
  fileSize: {
    type: Number,
    default: 200,
  },
  tips: {
    type: String,
    default:
      '支持扩展名doc /docx / xlsx / xls / 压缩文件 /pdf /jpg/jpeg/png文件，且不超过10MB',
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  // 上传文件类型
  // '' 表示附件和图片zip  file：表示work、excel、pdf、ppt等  video：表示视频 audio：表示音频 other：zip图片等  image: 图片
  fileType: {
    type: String,
    default: '',
  },
});
const emit = defineEmits([
  'get-file-list',
  'update:fileList',
  'update:fileList2',
]);
const accessStore = useAccessStore();
const uploadHeader = ref({
  authorization: 'authorization-text',
  tokenId: accessStore.accessToken,
});
const imageUrl = ref('');
const imageName = ref('');
const imageVisible = ref(false);

// 视频数据
const videoInfo = ref({});
const mp4Visible = ref(false);
const myVideo = ref(null);
const myPlayer = ref(null);
const pdfVisible = ref(false);
const pdfUrl = ref('');
const pdfInfo = ref({});
const fileList = ref([]);

// 文本
const txtVisible = ref(false);
const txtUrl = ref('');
const txtName = ref('');

watch(
  () => props.fileList,
  (newVal, oldVal) => {
    if (newVal !== oldVal) {
      fileList.value = newVal;
    }
  },
  {
    immediate: true,
    deep: true,
  },
);

// 文档excel\word\ppt\pdf
const fileTypes = new Set([
  'doc',
  'docx',
  'pdf',
  'ppt',
  'pptx',
  'txt',
  'xls',
  'xlsx',
]);

// 图片
const imageTypes = new Set(['gif', 'jpeg', 'jpg', 'png']);

// 音频
const audioTypes = new Set(['mp3']);

// 视频
const videoTypes = new Set(['avi', 'flv', 'mp4']);

// 压缩包
const zipTypes = new Set(['7z', 'rar', 'zip']);

const pdfTypes = new Set(['pdf']);

// 判断是否禁用上传和删除
const self_disabled = computed(() => {
  return props.disabled;
});

const checkFileType = (name) => {
  let extension = false;
  const extensionName = name
    .split('.')
    [name.split('.')?.length - 1].toLowerCase();
  // 文件、图片、压缩包
  if (props.fileType) {
    switch (props.fileType) {
      case 'audio': {
        // 音频
        extension = audioTypes.has(extensionName);

        break;
      }
      case 'file': {
        // 文档
        extension = fileTypes.has(extensionName);

        break;
      }
      case 'image': {
        // 图片
        extension = imageTypes.has(extensionName);

        break;
      }
      case 'other': {
        // 其他
        extension =
          fileTypes.has(extensionName) ||
          imageTypes.has(extensionName) ||
          zipTypes.has(extensionName) ||
          videoTypes.has(extensionName) ||
          pdfTypes.has(extensionName);

        break;
      }
      case 'video': {
        // 视频
        extension = videoTypes.has(extensionName);

        break;
      }
      case 'zip': {
        // 压缩包
        extension = zipTypes.has(extensionName);

        break;
      }
      // No default
    }
  } else {
    extension =
      fileTypes.has(extensionName) ||
      imageTypes.has(extensionName) ||
      zipTypes.has(extensionName) ||
      pdfTypes.has(extensionName);
  }
  return extension;
};

// 上传前校验
const beforeUpload = (file) => {
  const fileType = checkFileType(file.name);
  const isLt20M = file.size / 1024 / 1024 < props.fileSize;
  if (!fileType) {
    ElMessage.error('请上传正确格式文件!');
  }
  if (!isLt20M) {
    ElMessage.error(`上传不能超过 ${props.fileSize}MB!`);
  }
  return isLt20M && fileType;
};
// 上传成功回调函数
const handleSuccess = (response, file, fileist) => {
  console.log('上传成功--fileList', filelist);
  fileList.value = filelist.map((i) => {
    return i.response
      ? {
          name: i.response.data.originalFileName,
          url: i.response.data.fileName,
        }
      : { ...i };
  });
  emit('update:fileList', fileList.value);
  emit('update:fileList2', filelist);
};
// 上传失败回调函数
const handleError = (err, file, fileList) => {
  console.error('上传失败', err, file, fileList);
};
const handleRemove = (file, uploadFiles) => {
  console.log('handleRemove', file, uploadFiles);
};

const handlePreview = (uploadFile) => {
  const extensionName =
    uploadFile.url.split('.')[uploadFile.url.split('.').length - 1];
  // console.log(extensionName,'extensionName')
  // txt
  if (extensionName === 'txt') {
    txtVisible.value = true;
    txtUrl.value = uploadFile.url;
    txtName.value = uploadFile.name;
    fetch(`${imgUrl + uploadFile.url}`)
      .then((response) => response.text())
      .then((text) => {
        nextTick(() => {
          const previewElement = document.querySelector('#txt-preview');
          previewElement.innerHTML = text.replaceAll('\n', '<br>');
          // previewElement.textContent = text;
        });
      })
      .catch((error) => {
        console.error('Error previewing file:', error);
      });

    return;
  }

  // 文档/压缩包
  if (
    (extensionName !== 'pdf' && fileTypes.has(extensionName)) ||
    zipTypes.has(extensionName)
  ) {
    downloadFile(uploadFile.name, uploadFile.url);
  }

  // 图片
  if (imageTypes.has(extensionName)) {
    imageUrl.value = imgUrl + uploadFile.url;
    imageName.value = uploadFile.name;
    imageVisible.value = true;
  }

  // pdf
  if (pdfTypes.has(extensionName)) {
    pdfVisible.value = true;
    pdfUrl.value = imgUrl + uploadFile.url;
    pdfInfo.value = {
      name: uploadFile.name,
      uploadFile: uploadFile.url,
    };
  }

  // 音频/视频
  if (
    (audioTypes.has(extensionName) || videoTypes.has(extensionName)) &&
    (extensionName === 'mp4' || extensionName === 'mp3')
  ) {
    mp4Visible.value = true;
    videoInfo.value = {
      name: uploadFile.name,
      url: imgUrl + uploadFile.url,
      uploadFile: uploadFile.url,
    };
    nextTick(() => {
      onPlayer(imgUrl + uploadFile.url, uploadFile.name);
    });
  }
};

const onDialogClose = () => {
  if (myPlayer.value) {
    myPlayer.value.dispose();
    myPlayer.value = null;
  }
};

// 播放视频
const onPlayer = (url, name) => {
  myPlayer.value = videojs(myVideo.value, {
    autoplay: true,
    controls: true,
    sources: [
      {
        src: url,
        type: 'video/mp4',
      },
    ],
  });
};

// 文件下载
const downloadFile = (fileName, fileUrl) => {
  const url = imgUrl + fileUrl;

  const x = new window.XMLHttpRequest();
  x.open('GET', url, true);
  x.responseType = 'blob';
  x.addEventListener('load', () => {
    const url = window.URL.createObjectURL(x.response);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    a.click();
  });
  x.send();
};
const downloadImage = (fileUrl, fileName) => {
  fetch(fileUrl)
    .then((response) => response.blob())
    .then((blob) => {
      const blobURL = URL.createObjectURL(blob);
      const tempLink = document.createElement('a');
      tempLink.style.display = 'none';
      tempLink.href = blobURL;
      tempLink.setAttribute('download', fileName);

      document.body.append(tempLink);
      tempLink.click();
      tempLink.remove();
      URL.revokeObjectURL(blobURL);
    })
    .catch((error) => console.error(error));
};

const handleExceed = (files, uploadFiles) => {
  console.log('handleExceed', files, uploadFiles);
  ElMessage.warning(
    `上传限制是${props.uploadLimit}个，你选择了限制上传${files.length}个文件,现在上传了${
      files.length + uploadFiles.length
    }个文件，如需要请修改上传限制`,
  );
};

const beforeRemove = (uploadFile, uploadFiles) => {
  return ElMessageBox.confirm(`是否取消上传 ${uploadFile.name} ?`).then(
    () => true,
    () => false,
  );
};
</script>

<template>
  <el-upload
    v-model:file-list="fileList"
    :action="uploadUrl"
    :before-upload="beforeUpload"
    :data="uploadData"
    :disabled="self_disabled"
    :headers="uploadHeader"
    :limit="uploadLimit"
    :on-error="handleError"
    :on-exceed="handleExceed"
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :on-success="handleSuccess"
    class="upload"
    multiple
  >
    <el-button
      v-if="!self_disabled"
      :disabled="self_disabled"
      link
      type="primary"
    >
      点击上传
    </el-button>
    <template v-if="!self_disabled" #tip>
      <div class="el-upload__tip">
        {{ tips }}
      </div>
    </template>
  </el-upload>
  <!-- 图片 -->
  <el-dialog v-model="imageVisible">
    <img :src="imageUrl" alt="预览图片" style="width: 100%" w-full />
    <template #footer>
      <el-button @click="imageVisible = false">取 消</el-button>
      <el-button type="primary" @click="downloadImage(imageUrl, imageName)">
        下 载
      </el-button>
    </template>
  </el-dialog>
  <!-- mp4 -->
  <el-dialog
    v-model="mp4Visible"
    :title="videoInfo.name"
    align-center
    destroy-on-close
    @close="onDialogClose"
  >
    <video
      ref="myVideo"
      class="video-js"
      height="400"
      preload="auto"
      width="600"
    ></video>
    <template #footer>
      <el-button @click="mp4Visible = false">取 消</el-button>
      <el-button
        type="primary"
        @click="downloadFile(videoInfo.name, videoInfo.uploadFile)"
      >
        下 载
      </el-button>
    </template>
  </el-dialog>
  <!-- pdf -->
  <el-dialog v-model="pdfVisible" @close="pdfVisible = false">
    <iframe
      :src="`${pdfUrl}#toolbar=0`"
      style="width: 100%; height: 500px"
    ></iframe>
    <template #footer>
      <el-button @click="pdfVisible = false">取 消</el-button>
      <el-button
        type="primary"
        @click="downloadFile(pdfInfo.name, pdfInfo.uploadFile)"
      >
        下 载
      </el-button>
    </template>
  </el-dialog>
  <!-- txt -->
  <el-dialog v-model="txtVisible" @close="txtVisible = false">
    <div id="txt-preview"></div>
    <template #footer>
      <el-button @click="txtVisible = false">取 消</el-button>
      <el-button type="primary" @click="downloadFile(txtName, txtUrl)">
        下 载
      </el-button>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.video-js {
  width: 100%;
}

.upload {
  width: 100%;
}
</style>
